﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using CreditAgricole.Framework;
using Microsoft.SharePoint.Workflow;

namespace CreditAgricole.Application
{
    public static class DataMep
    {
        #region MEP List Request

        /// <summary>
        /// Get all items in list
        /// </summary>
        /// <param name="siteId">Current site ID</param>
        /// <param name="webId">Current web ID</param>
        /// <param name="listTitle">List title where tasks were created</param>
        /// <returns>List of MepObj</returns>
        public static List<VOBase> GetMepObj(Guid siteId, Guid webId, string listTitle)
        {
            List<VOBase> mepObjs = new List<VOBase>();
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite site = new SPSite(siteId))
                {
                    using (SPWeb web = site.OpenWeb(webId))
                    {
                        SPList list = web.Lists.TryGetList(listTitle);
                        if (list != null)
                        {
                            SPQuery query = QueryBuilder.GetSelectedItemsOrderBy(Constants.CreatedDateField);
                            SPListItemCollection items = list.GetItems(query);
                            AddItemsToMepList(mepObjs, items, -1);
                        }
                    }
                }
            });
            return mepObjs;
        }

        /// <summary>
        /// Get all items created by current user
        /// </summary>
        /// <param name="siteId">Current site ID</param>
        /// <param name="webId">Current web ID</param>
        /// <param name="listTitle">List title where tasks were created</param>
        /// <returns>List of MepObj</returns>
        public static List<VOBase> GetCreatedTasksByWorkflowStatus(Guid siteId, Guid webId, string listTitle, 
                                                                    int currentUserId, 
                                                                    string workflowStatusNumber, 
                                                                    Constants.CamlQueryOperator queryOperator)
        {
            List<VOBase> mepObjs = new List<VOBase>();
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite site = new SPSite(siteId))
                {
                    using (SPWeb web = site.OpenWeb(webId))
                    {
                        SPList list = web.Lists.TryGetList(listTitle);
                        if (list != null)
                        {
                            IDictionary<string, string> filter = new Dictionary<string, string>();
                            string workflowInternalName = SPHelper.GetInternalFieldName(list, Constants.WorkflowAssociationName);
                            if (!string.IsNullOrEmpty(workflowInternalName))
                            {
                                filter.Add(workflowInternalName, workflowStatusNumber);
                                SPQuery query = QueryBuilder.GetSelectedItemsWithLookup("Lookup", "Author", 
                                                                                         MappingTool.CatchNull(currentUserId), 
                                                                                         Constants.CamlQueryOperator.Equal, 
                                                                                         filter, queryOperator);
                                SPListItemCollection selectedItems = list.GetItems(query);
                                AddItemsToMepList(mepObjs, selectedItems, currentUserId);
                            }
                        }
                    }
                }
            });
            return mepObjs;
        }

        /// <summary>
        /// Get items with workflow status mentionned in parameter
        /// </summary>
        /// <param name="siteId">Current site ID</param>
        /// <param name="webId">Current web ID</param>
        /// <param name="listTitle">List title where tasks were created</param>
        /// <param name="status">Workflow status</param>
        /// <returns>List of MepObj</returns>
        public static List<VOBase> GetItemsByProdStatus(Guid siteId, Guid webId, string listTitle, string prodStatus, Constants.CamlQueryOperator prodStatusQueryOperator)
        {
            List<VOBase> mepObjs = new List<VOBase>();
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite site = new SPSite(siteId))
                {
                    using (SPWeb web = site.OpenWeb(webId))
                    {
                        SPList list = web.Lists.TryGetList(listTitle);
                        if (list != null)
                        {
                            string workflowInternalName = SPHelper.GetInternalFieldName(list, Constants.WorkflowAssociationName);
                            if (!string.IsNullOrEmpty(workflowInternalName))
                            {
                                IDictionary<string, string> filter = new Dictionary<string, string>();
                                filter.Add(Constants.MepStatusField, prodStatus);
                                filter.Add(workflowInternalName, "16");
                                SPQuery query = QueryBuilder.GetSelectedItems(workflowInternalName, "16", Constants.CamlQueryOperator.Equal, Constants.MepStatusField, prodStatus, prodStatusQueryOperator);
                                SPListItemCollection selectedItems = list.GetItems(query);
                                AddItemsToMepList(mepObjs, selectedItems, -1);
                            }
                        }
                    }
                }
            });
            return mepObjs;
        }

        /// <summary>
        /// Get the list of items awaiting to be validated by the current user
        /// </summary>
        /// <param name="siteId">The current site id</param>
        /// <param name="webId">The current web Id</param>
        /// <param name="listTitle"></param>
        /// <returns></returns>
        public static List<VOBase> GetTasksAssignedToMeByWorkflowStatus(Guid siteId, Guid webId, string listTitle, 
                                                                       int currentUserId, 
                                                                       Constants.CamlQueryOperator userQueryOperator, 
                                                                       string workflowStatusNumber, 
                                                                       Constants.CamlQueryOperator workflowQueryOperator)
        {
            List<VOBase> mepObjs = new List<VOBase>();
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite site = new SPSite(siteId))
                {
                    using (SPWeb web = site.OpenWeb(webId))
                    {
                        SPList tasks = web.Lists.TryGetList(Constants.WorkflowTasksList);
                        SPList list = web.Lists.TryGetList(listTitle);
                        if (tasks != null && list != null)
                        {
                            IDictionary<string, string> filter = new Dictionary<string,string>();
                            filter.Add("WorkflowListId", MappingTool.CatchNull(list.ID));
                            filter.Add("WorkflowOutcome", string.Empty);
                            SPQuery query = QueryBuilder.GetSelectedItemsWithLookup("User", "AssignedTo", MappingTool.CatchNull(currentUserId), userQueryOperator, filter, workflowQueryOperator); 
                            SPListItemCollection taskItems = tasks.GetItems(query);
                            try
                            {
                                if (taskItems.Count > 0)
                                {
                                    string listPath = string.Format("{0}/{1}/", web.Url, list.RootFolder.Url);
                                    SPListItemCollection listItems = GetTaskItemsFromList(list, taskItems, workflowStatusNumber, listPath);
                                    AddItemsToMepList(mepObjs, listItems, currentUserId);
                                }
                            }
                            catch (Exception e)
                            {
                                CALoggingHelper.AddErrorEntry(e.Message);
                            }
                        }
                    }
                }
            });
            return mepObjs;
        }

        /// <summary>
        /// Get the list of items awaiting to be validated by the current user
        /// </summary>
        /// <param name="siteId">The current site id</param>
        /// <param name="webId">The current web Id</param>
        /// <param name="listTitle"></param>
        /// <returns></returns>
        public static List<VOBase> GetItemsByDate(Guid siteId, Guid webId, string listTitle, int currentUserId, string fieldDateName, string startDate, string endDate)
        {
            List<VOBase> mepObjs = new List<VOBase>();
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite site = new SPSite(siteId))
                {
                    using (SPWeb web = site.OpenWeb(webId))
                    {
                        SPList list = web.Lists.TryGetList(listTitle);
                        if (list != null)
                        {
                            SPQuery query = QueryBuilder.GetItemsBetweenDates(fieldDateName, startDate, endDate);
                            SPListItemCollection items = list.GetItems(query);
                            try
                            {
                                if (items.Count > 0)
                                {
                                    AddItemsToMepList(mepObjs, items, currentUserId);
                                }
                            }
                            catch (Exception e)
                            {
                                CALoggingHelper.AddErrorEntry(e.Message);
                            }
                        }
                    }
                }
            });
            return mepObjs;
        }
        #endregion

        #region Tool Methods

        /// <summary>
        /// Insert map all items and insert them in MepObjs list
        /// </summary>
        /// <param name="mepObjs">MepObjs List</param>
        /// <param name="items">Items to map</param>
        private static void AddItemsToMepList(List<VOBase> mepObjs, SPListItemCollection items, int currentUserId)
        {
            try
            {
                foreach (SPListItem item in items)
                {
                    VOMep mepObj = GetMappedObj(item, currentUserId);
                    mepObjs.Add(mepObj);
                }
            }
            catch (SPException ex)
            {
                CALoggingHelper.AddErrorEntry(ex.Message);
            }
        }

        /// <summary>
        /// Map object from List item
        /// </summary>
        /// <param name="item">List item</param>
        /// <returns>mapped object</returns>
        private static VOMep GetMappedObj(SPListItem item, int currentUserId)
        {
            VOMep mepObj = VOMapperMep.GetVOMepFromListItem(item);
            SPUser author = GetSPUser(item, Constants.AuthorField).User;
            SPUser currentApprover = SPHelper.GetCurrentApprover(item);
            
            mepObj.Entity = GetLookupValuesFromItem(item, Constants.EntityField);
            mepObj.Domaine = GetLookupValuesFromItem(item, Constants.DomainField);

            mepObj.Author = (author != null ? author.Name : string.Empty);
            mepObj.CurrentApprover = (currentApprover != null ? currentApprover.Name : string.Empty);
            mepObj.Workflow = SPHelper.GetWorkflowFieldDisplayText(item);
            if (currentApprover != null)
            {
                if (currentApprover.ID == currentUserId && mepObj.Workflow == "In Progress")
                {
                    mepObj.NeedsApproval = true;
                }
            }
            return mepObj;
        }

        /// <summary>
        /// Get the SPUser object from Item 
        /// </summary>
        /// <param name="item">Item from the list</param>
        /// <param name="fieldName">field name containing the user</param>
        /// <returns>SPUser objectof the specified item</returns>
        private static SPFieldUserValue GetSPUser(SPListItem item, string fieldName)
        {
            SPFieldUserValue fieldValue = null;
            try
            {
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    SPFieldUser field = item.Fields.GetField(fieldName) as SPFieldUser;
                    if (field != null && item[fieldName] != null)
                    {
                        fieldValue = field.GetFieldValue(MappingTool.CatchNull(item[fieldName])) as SPFieldUserValue;
                    }
                });
            }
            catch (SPException ex)
            {
                CALoggingHelper.AddErrorEntry(ex.Message);
            }
            return fieldValue;
        }
        
        /// <summary>
        /// Get item from list in parameter
        /// </summary>
        /// <param name="list">List where item is got</param>
        /// <param name="taskItem">Item from task list</param>
        /// <param name="worflowStatus">worflowStatus</param>
        /// <returns></returns>
        private static SPListItemCollection GetTaskItemsFromList(SPList list, SPListItemCollection taskItems, string worflowStatus, string listPath)
        {
            SPListItemCollection listItems = null;
            List<string> fileNameList = new List<string>();
            foreach (SPListItem taskItem in taskItems)
            {
                SPFieldUrl url = (SPFieldUrl)taskItem.Fields.GetField(Constants.WorkflowLinkField);
                if (url != null && taskItem[Constants.WorkflowLinkField] != null)
                {
                    SPFieldUrlValue fieldValue = url.GetFieldValue(MappingTool.CatchNull(taskItem[Constants.WorkflowLinkField])) as SPFieldUrlValue;
                    if (fieldValue != null)
                    {
                        string fileName = fieldValue.Url.Replace(listPath, string.Empty);
                        fileNameList.Add(fileName);
                    }
                }
            }
            string workflowInternalName = SPHelper.GetInternalFieldName(list, Constants.WorkflowAssociationName);
            if (!string.IsNullOrEmpty(workflowInternalName))
            {
                SPQuery query = QueryBuilder.GetQueryWithFileNames(Constants.WorkflowStatusType, workflowInternalName, worflowStatus, fileNameList);
                listItems = list.GetItems(query);
            }
            return listItems;
        }

        private static List<string> GetLookupValuesFromItem(SPListItem item, string fieldName)
        {
            List<string> entities = new List<string>();
            if (item[fieldName] != null)
            {
                SPFieldLookupValueCollection valuesField = item[fieldName] as SPFieldLookupValueCollection;
                foreach (SPFieldLookupValue value in valuesField)
                {
                    entities.Add(value.LookupValue);
                }
            }
            return entities;
        }
        #endregion
    }
}
